﻿using System;
using System.Collections.Generic;

namespace Heaven.Engine.Concurrency
{
    /// <summary>
    /// This class helps us to 
    /// work with deferred actions
    /// </summary>
    public class DeferredActions
    {
        #region Fields

        // Queue of deferred actions
        Queue<DeferredActionDelegate> actions = new Queue<DeferredActionDelegate>();
        Queue<object[]> parameters = new Queue<object[]>();

        #endregion

        #region Properties

        /// <summary>
        /// Is the collection changed?
        /// </summary>
        public bool IsChanged
        {
            get 
            {
                lock (actions)
                {
                    return actions.Count != 0;
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Defers an action
        /// </summary>
        /// <param name="action">A deferred action</param>
        /// <param name="parameters">Input parameters</param>
        public void Add(DeferredActionDelegate action, params object[] inputs)
        {
            lock (actions)
            {
                actions.Enqueue(action);
                parameters.Enqueue(inputs);
            }
        }

        /// <summary>
        /// Performs all deferred actions
        /// </summary>
        public void Perform()
        {
            lock (actions)
            {
                DeferredActionDelegate action = null;
                object[] inputs = null;
                while (actions.Count != 0)
                {
                    action = actions.Dequeue();
                    inputs = parameters.Dequeue();
                    action.Invoke(inputs);
                }
            }
        }

        #endregion
    }

    /// <summary>
    /// Represents deferred action delegate
    /// </summary>
    /// <param name="parameters">Input parameters</param>
    public delegate void DeferredActionDelegate(object[] parameters);
}
